﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShevaEngine.Core.Modules.Scenes;
using ShevaEngine.Core.Modules.Graphics;
using ShevaEngine.Core.Interfaces;
using Microsoft.Xna.Framework;
using ShevaEngine.Core.GameLogic.Triggers;
using Microsoft.Xna.Framework.Graphics;

namespace ShevaEngine.Core.GameLogic
{
    /// <summary>
    /// Game Logic.
    /// </summary>
    public abstract class GameLogic : IShevaEngineGamePart
    {
        /// <summary>Game core.</summary>
        public GameCore GameCore;
        /// <summary>Scene.</summary>
        public Scene Scene;
        /// <summary>Viewport.</summary>
        public List<GraphicsViewport> Viewports;
        /// <summary>Renderer.</summary>
        public IRenderer Renderer;
        /// <summary>Triggers.</summary>
        private TriggersManager Triggers;
        /// <summary>Updateables</summary>
        private List<IUpdateAble> Updateables;

        /// <summary>
        /// Constructor.
        /// </summary>
        public GameLogic()
        {
            this.GameCore = new GameCore();
            this.Viewports = new List<GraphicsViewport>();
            this.Triggers = new TriggersManager();
            this.Updateables = new List<IUpdateAble>();
        }

        /// <summary>
        /// Method adds scene object.
        /// </summary>
        /// <param name="sceneObject"></param>
        public virtual void AddSceneObject(SceneObject sceneObject)
        {
            this.Scene.AddObjectInScene(sceneObject);

            if (sceneObject is Trigger)
                this.Triggers.AddTrigger(sceneObject as Trigger);

            if (sceneObject is IGameCoreObject)
                this.GameCore.RegisterGameCoreObject(sceneObject as IGameCoreObject);

            if (sceneObject is IUpdateAble)
                this.Updateables.Add(sceneObject as IUpdateAble);

            foreach (SceneObject child in sceneObject.AttachedSceneObjects)
                this.AddSceneObject(child);            
        }

        /// <summary>
        /// Method removes scene object from scene.
        /// </summary>
        /// <param name="sceneObject"></param>
        public virtual void RemoveSceneObject(SceneObject sceneObject)
        {
            this.Scene.RemoveObjectFromScene(sceneObject);

            //if (sceneObject is Trigger)
            //    this.Triggers.RemoveTrigger(sceneObject as Trigger);

            if (sceneObject is IGameCoreObject)
                this.GameCore.UnregisterGameCoreObject(sceneObject as IGameCoreObject);

            if (sceneObject is IUpdateAble)
                this.Updateables.Remove(sceneObject as IUpdateAble);

            foreach (SceneObject child in sceneObject.AttachedSceneObjects)
                this.RemoveSceneObject(child);            
        }


        /// <summary>
        /// Activate.
        /// </summary>
        public virtual void Activate()
        {                        
        }

        /// <summary>
        /// Deactivate.
        /// </summary>
        public virtual void Deactivate()
        {
        }

        /// <summary>
        /// Load resources.
        /// </summary>
        public virtual void LoadResources()
        {
        }

        /// <summary>
        /// Unload resources.
        /// </summary>
        public virtual void UnloadResources()
        {
        }

        /// <summary>
        /// Update.
        /// </summary>
        /// <param name="time"></param>
        public virtual void Update(GameTime time)
        {            
            this.Triggers.Update(time);

            for (int i = this.Updateables.Count - 1; i >= 0; i--)
                this.Updateables[i].Update(time);
        }

        /// <summary>
        /// Draw.
        /// </summary>
        public virtual void Draw()
        {
            this.Renderer.CreateShadowMaps();                        

            foreach (GraphicsViewport viewport in this.Viewports)
            {
                Texture2D scene = viewport.Draw();

                ShevaEngine.Instance.SpriteBatch.Begin();
                
                ShevaEngine.Instance.SpriteBatch.Draw(scene, viewport.PositionSize, Color.White);

                ShevaEngine.Instance.SpriteBatch.End();
            }            
        }
    }
}
